#!/usr/bin/perl
#
# Coded by Loni - loni@securityforest.com
# Updated:  12/02/2005
#
# Client Utility for the ExploitTree CVS Repository on SecurityForest.com

$ver = "v0.6";
$name = "ExploitTree.pl";

$winexe = "no"; #Only applicable when distributed as an exe with binary unix utilities
if ($winexe eq "yes") { 
	$name = "ExploitTree.exe"; 
	$dir = $0; $dir =~ s/\\$name//;
	$ENV{'PATH'} = "$dir\\bin;$ENV{'PATH'}";
}

if ($#ARGV < 0) { &usage(); } $username = @ARGV[0]; 

sub usage {
	print "ExploitTree $ver\nCoded by Loni - loni\@securityforest.com\nhttp:\/\/www.SecurityForest.com\n\n";
	print "Normal Usage:\n";
	print " - Run this tool from the directory that already or will contain\n";
	print "   the directory ExploitTree.\n";
	print " - To download the repository run \"$name anonymous\" (blank password).\n\n";
	print "ExploitTree Administrators and Contributers Usage:\n";
	print " - To log in to the repository run \"$name <your_nick>\", enter your\n";
	print "   password when prompted.\n";
	print " - When updating the repository, close the default editor\n";
 	print "   and then c\<enter\> to continue when prompted.\n";
 	print "   eg. vi:      type \:q\<enter\>\n";
 	print "   eg. nano:    type \<ctrl\>x\n";
 	print "   eg. notepad: type \<alt\>f,x\n\n"; 
	exit(1); 
}

$server = "cvs.securityforest.com"; $rep = "\/home/security/cvsroot";

$loggedin = 0;
$refreshbranches = 1;
&master();


sub master {
	if ($username eq "anonymous") {
		print "\nExploitTree Client Utility Manager $ver\n----------------------------------------\n\n";
		print "1\) Initialize (first time download)\n"; 
		print "2\) Update Repository\n";
		print "3\) Print Exploit Statistics\n";
		print "q\) Quit\n\n> ";
		chomp($choice = <STDIN>);
		if ($choice == 1) { &login($username); &initial_download(); }
		if ($choice == 2) { &version(); &login($username); &update_local(); }
		if ($choice == 3) { &version(); &stats(); print "\nHit Enter to continue>"; <STDIN>; &master(); }
		elsif ($ch_list == "q") { print "Quiting...\n"; exit(1); } 
	} else {
		print "\nExploitTree Client Utility Admin Manager $ver\n----------------------------------------\n\n";
		print "1\) Initialize (first time download)\n"; 
		print "2\) Update Local Copy\n"; 
		print "3\) Update Repository - Upload files from one local branch\n"; 
		print "4\) Update Repository - Add & upload ALL new branches from\n";
		print "                       local copy\n"; 
		print "5\) Update Repository - Add & upload ALL new branches\/files from\n";
		print "                       local copy *recursivly* (ie. slow)\n"; 
		print "6\) Print Exploit Statistics\n";
		print "+---------------------------------------\nq\) Quit\n\n> ";
		chomp($choice = <STDIN>);
		if ($choice == 1) { &login($username); &initial_download();}
		if ($choice == 2) { &version(); &login($username); &update_local(); &master();}
		if ($choice == 3) { &version(); &login($username); &branches(); &update_repos_one(); &master();}
		if ($choice == 4) { &version(); &login($username); &new_branches(); &branches(); &update_repos_one(); &commit(); &master();}
		if ($choice == 5) { &version(); &login($username); &new_branches(); &branches(); &update_repos_all(); &commit(); &master();}
		if ($choice == 6) { &version(); &stats(); print "\nHit Enter to continue>"; <STDIN>; &master(); }
		elsif ($ch_list == "q") { print "Quiting...\n"; exit(1); }    
	}
}

sub version {
	@latest_ver = &readfile("ExploitTree\/_Ver");
	chomp($latest_ver[0]); chop($latest_ver[0]);
	if ($latest_ver[0] ne $ver) {
		print "Please use $name $latest_ver[0] - Available at SecurityForest.com\n";
		print "http:\/\/www.securityforest.com\/downloads\/ExploitTree-pl.tar.gz or ExploitTree-Win32.zip";
		exit(1);
	}
}

sub branches {
	if ($refreshbranches == 1) {
		undef(@branches);
		system("cd ExploitTree && ls -R * |grep : |grep -v CVS > ../branches.txt && cd ..");
		@branches_tmp = &readfile("branches.txt");
		foreach $branch_tmp (@branches_tmp) { 
			chomp($branch_tmp);
			if ($winexe eq "yes") { $branch_tmp=~s/=://; } else { $branch_tmp=~s/://; }
			push(@branches,$branch_tmp);
		}
		$refreshbranches == 0;
	}	
}

sub new_branches {
	$refreshbranches = 1;
	undef(@branches2);
	system("cd ExploitTree && ls -R * > ../branches2.txt && cd ..");
	@branches_tmp2 = &readfile("branches2.txt");
	$bdots=0;
	$branch_has_SF="no";
	foreach $branch_tmp2 (@branches_tmp2) { 
		chomp($branch_tmp2);
		if ($branch_tmp2=~/:/) { if ($bdots == 0) { $branch_tmp3 = $branch_tmp2; } $bdots++; }
		if ($branch_tmp2=~/_SecurityForest/) { $branch_has_SF="yes"; }
		if ($bdots == 1 && $branch_has_SF eq "yes" ) { $bdots=0; $branch_has_SF="no"; }
		else { 
			if ($bdots == 2) { if ($branch_tmp3!~/CVS/) {	
				if ($winexe eq "yes") { $branch_tmp3=~s/=://; } else { $branch_tmp3=~s/://; }
				push(@branches2,$branch_tmp3); 
			} 
			$branch_tmp3 = $branch_tmp2; $bdots=1; 
			} 
		}
	}
	$branch_num2 = 0;
	for $branch_num2 (0..$#branches2) { &addbranch($branch_num2); }
}

sub readfile {		#read in a files contents
	undef @readfile_contents;
	my ($readfile) =  @_;
	open READFILE, $readfile or die "Cannot open $readfile for read :$!\n";
	while (<READFILE>) { push (@readfile_contents, $_); } 
	close READFILE;
	return(@readfile_contents);
}

sub login {
	my ($username) = @_;
	if ($username eq "anonymous") { print "Password is blank (press enter), then wait...\n\n"; }
	$cvsconnect = "cvs -d:pserver:$username\@$server:$rep";
	if ($loggedin == 0) { system("$cvsconnect login"); $loggedin = 1; }	
}

sub initial_download { system("$cvsconnect -z5 co ExploitTree"); }

sub update_local { system("cd ExploitTree && $cvsconnect update -dP && cd .."); } 
# -d (build directories if new directories have been added to the repository since your 
# checkout or last update) and -P (leave empty directories out of your working copy)

sub update_repos_one() {
	$branch_num = "0";
	print "\nChoose a branch to update\n-----------------------------\n";
	foreach $branch (@branches) { print "$branch_num\) $branch\n"; $branch_num++; }
	print "\nbranch> ";
	chomp($branch_choice = <STDIN>);
	&update($branch_choice);
}

sub update_repos_all {
	$branch_num = 0;
	for $branch_num (0..$#branches) { &update($branch_num); }
}

sub update {
	my ($branch_num) = @_;
	print "Updating @branches[$branch_num]\n";
	system("cd ExploitTree && $cvsconnect add @branches[$branch_num]\/*.* && cd ..");
	system("cd ExploitTree && $cvsconnect commit @branches[$branch_num] && cd ..");
}

sub addbranch {
	my ($branch_num) = @_;
	print "Adding @branches2[$branch_num2]\n";
	system("cd ExploitTree && $cvsconnect add @branches2[$branch_num2] && cd ..");
	system("cd ExploitTree && cp _SecurityForest @branches2[$branch_num2] && cd ..");
	system("cd ExploitTree && $cvsconnect add @branches2[$branch_num2]\/_SecurityForest && cd ..");
}

sub commit { system("cd ExploitTree && $cvsconnect commit && cd .."); }

sub stats {
	print "Please wait while calculating...";
	system("ls -R ExploitTree | grep -v \":\\|CVS\\|Entries\\|Entries.Log\\|Repository\\|Root\\|_SecurityForest\" | grep . | grep -e [*.*] | wc -l > stats.txt");
	@stats = &readfile("stats.txt");
	print "\nTotal Exploits: $stats[0]\n";
}

#EOF

